package game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList; // 导入线程安全集合

/**
 * 爱心粒子系统模拟程序
 * 修复了并发修改异常，确保多线程安全
 */
public class HeartParticleSystem extends JFrame {

    // 粒子系统的主面板
    private final ParticlePanel particlePanel;

    public HeartParticleSystem() {
        super("爱心粒子系统");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        particlePanel = new ParticlePanel();
        add(particlePanel);

        setSize(800, 600);
        setLocationRelativeTo(null);
        setVisible(true);

        particlePanel.startAnimation();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(HeartParticleSystem::new);
    }

    private class ParticlePanel extends JPanel {

        // 关键修复：使用线程安全的CopyOnWriteArrayList替代ArrayList
        private final List<Particle> particles = new CopyOnWriteArrayList<>();
        private static final int INITIAL_PARTICLES = 300;
        private static final double GRAVITY = 0.1;
        private volatile boolean isRunning;
        private boolean isInitialized = false;
        private int centerX, centerY;
        private static final int HEART_SIZE = 150;

        public ParticlePanel() {
            setBackground(Color.BLACK);
            isRunning = true;

            addComponentListener(new ComponentAdapter() {
                @Override
                public void componentResized(ComponentEvent e) {
                    if (!isInitialized) {
                        centerX = getWidth() / 2;
                        centerY = getHeight() / 2 - 50;
                        initializeHeartParticles();
                        isInitialized = true;
                    }
                    repaint();
                }
            });

            // 鼠标点击添加粒子（事件线程）
            addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                    for (int i = 0; i < 15; i++) {
                        particles.add(new Particle(e.getX(), e.getY()));
                    }
                }
            });

            // 鼠标拖动添加粒子（事件线程）
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseDragged(MouseEvent e) {
                    for (int i = 0; i < 3; i++) {
                        particles.add(new Particle(e.getX(), e.getY()));
                    }
                }
            });
        }

        private void initializeHeartParticles() {
            Random random = new Random();

            for (int i = 0; i < INITIAL_PARTICLES; i++) {
                double t = (random.nextDouble() * 2 - 1) * Math.PI;
                double x = 16 * Math.pow(Math.sin(t), 3);
                double y = 13 * Math.cos(t) - 5 * Math.cos(2*t) - 2 * Math.cos(3*t) - Math.cos(4*t);

                double scale = HEART_SIZE / 16.0;
                double particleX = centerX + x * scale;
                double particleY = centerY - y * scale;

                particleX += (random.nextDouble() - 0.5) * 15;
                particleY += (random.nextDouble() - 0.5) * 15;

                Particle p = new Particle(particleX, particleY);
                p.velocityX = (particleX - centerX) * 0.01;
                p.velocityY = (particleY - centerY) * 0.01;
                particles.add(p);
            }
        }

        public void startAnimation() {
            // 动画线程（与事件线程是不同线程）
            Thread animationThread = new Thread(() -> {
                while (isRunning) {
                    if (isInitialized) {
                        updateParticles();
                    }
                    repaint();
                    try {
                        Thread.sleep(16);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            });
            animationThread.start();
        }

        private void updateParticles() {
            // 移除超出数量的粒子（动画线程操作）
            if (particles.size() > 500 && Math.random() < 0.1) {
                particles.remove(0);
            }

            // 遍历并更新粒子（动画线程操作）
            for (Particle p : particles) {
                p.velocityY += GRAVITY;
                p.x += p.velocityX;
                p.y += p.velocityY;

                if (p.x <= p.radius || p.x >= getWidth() - p.radius) {
                    p.velocityX *= -0.9;
                }

                if (p.y <= p.radius || p.y >= getHeight() - p.radius) {
                    p.velocityY *= -0.9;
                    if (p.y >= getHeight() - p.radius) {
                        p.y = getHeight() - p.radius;
                    }
                    if (p.y <= p.radius) {
                        p.y = p.radius;
                    }
                }

                p.changeColorSlightly();
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            if (isInitialized) {
                for (Particle p : particles) {
                    g2d.setColor(p.color);
                    g2d.fillOval(
                            (int) (p.x - p.radius),
                            (int) (p.y - p.radius),
                            (int) (2 * p.radius),
                            (int) (2 * p.radius)
                    );
                }

                g2d.setColor(Color.PINK);
                g2d.drawString("点击或拖动鼠标创建粒子 | 粒子数量: " + particles.size(), 10, 20);
            }
        }

        @Override
        public void setSize(int width, int height) {
            super.setSize(width, height);
            setPreferredSize(new Dimension(width, height));
        }
    }

    private static class Particle {
        double x, y;
        double velocityX, velocityY;
        double radius;
        Color color;
        private static final Random random = new Random();

        public Particle(double x, double y) {
            this.x = x;
            this.y = y;
            this.radius = 3 + random.nextDouble() * 8;
            this.velocityX = (random.nextDouble() - 0.5) * 3;
            this.velocityY = (random.nextDouble() - 0.5) * 3;

            int r = 200 + random.nextInt(56);
            int g = random.nextInt(100);
            int b = random.nextInt(150);
            this.color = new Color(r, g, b, 200);
        }

        public void changeColorSlightly() {
            int r = color.getRed();
            int g = color.getGreen();
            int b = color.getBlue();

            r = Math.min(255, Math.max(0, r + (random.nextInt(3) - 1)));
            g = Math.min(100, Math.max(0, g + (random.nextInt(3) - 1)));
            b = Math.min(150, Math.max(0, b + (random.nextInt(3) - 1)));

            color = new Color(r, g, b, 200);
        }
    }
}